package registrar;

import com.itheima.customer.CustomerBeanNameGenerator;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AspectJTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;

/***
 * 自定义bean导入注册器
 * 默认的BeanNameGenerator是AnnotationBeanNameGenerator 类名首字母小写+类名
 * @author 黑马程序员
 * @Company http://www.itheima.com
 */
public class CustomeImportDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    //表达式（ASPECTJ表达式）
    private String expression;
    //使用者指定的包名
    private String customePackage;

    public CustomeImportDefinitionRegistrar() {
        try {
            Properties loadAllProperties = PropertiesLoaderUtils.loadAllProperties("customeimport.properties");
            expression = loadAllProperties.getProperty("custome.importselector.expression");
            customePackage = loadAllProperties.getProperty("custome.importselector.customePackage");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 实现注册bean的功能(它是通过扫描指定包完成的)
     * @param importingClassMetadata
     * @param registry
     */
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //1.定义扫描包的名称
        List<String> basePackages = null;

        // 2.判断有@Import注解的类上是否有@ComponentScan注解
        if (importingClassMetadata.hasAnnotation(ComponentScan.class.getName())) {

            //3.取出@ComponentScan注解的属性
            Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName());
            // 4.取出属性名称为basePackages属性的值
            basePackages = new ArrayList(Arrays.asList((String[]) annotationAttributes.get("basePackages")));
        }

        // 5.判断是否有此属性（如果没有ComponentScan注解则属性值为null，如果有 ComponentScan注解，则basePackages默认为空数组）
        if (basePackages == null || basePackages.size() == 0) {
            String basePackage = null;
            try {
                //6.取出包含@Import注解类的包名
                basePackage = Class.forName(importingClassMetadata.getClassName()).getPackage().getName();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }

            //7.存入数组中
            basePackages = new ArrayList<>();
            basePackages.add(basePackage);
        }

        //判断是否配置了用户自定义包
        if(!StringUtils.isEmpty(customePackage)){
            basePackages.add(customePackage);
        }

        //8.创建类路径扫描器
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false);
        //9.创建类型过滤器(此处使用切入点表达式类型过滤器)
        TypeFilter typeFilter = new AspectJTypeFilter(expression, this.getClass().getClassLoader());
        //10.给扫描器加入类型过滤器
        scanner.addIncludeFilter(typeFilter);
        //设置扫描bean的名字生成规则
        scanner.setBeanNameGenerator(new CustomerBeanNameGenerator());
        //11.扫描指定包
        scanner.scan(basePackages.toArray(new String[basePackages.size()]));
    }

}
